---
id: createtcpclient
sidebar_position: 3
title: 创建TcpClient
sidebar_label: 6.3 创建TcpClient
---

## 一、说明
TcpClient是Tcp系客户端基类，他直接参与tcp的连接、发送、接收、处理、断开等，他的业务与服务器的**SocketClient**是一一对应的。

## 二、特点

- 简单易用。
- IOCP多线程。
- 内存池支持
- 高性能
- 适配器预处理，一键式解决**分包**、**粘包**、对象解析(如HTTP，Json)等。
- 超简单的同步发送、异步发送、接收等操作。
- 基于委托、插件驱动，让每一步都能执行AOP。

## 三、产品应用场景

- 所有Tcp基础使用场景：可跨平台、跨语言使用。
- 自定义协议解析场景：可解析任意数据格式的TCP数据报文。

## 四、客户端工作流程
![](https://cdn.nlark.com/yuque/0/2022/jpeg/25438888/1644495854071-a320a8b5-85ba-4563-a2fa-5bd573af850c.jpeg)


## 五、可配置项
| **属性名** | **属性描述** |
| --- | --- |
| SetBufferLength | 缓存池容量（单位：byte），默认1024*64。
设置建议：
1. 如果数据包较小，建议10k左右的值。更加节约内存。
2. 如果数据包较大，例如文件传输等，建议64k，甚至更大的值。
3. 该值虽然无上限，但是一般不要超过1Mb，不然不仅没意义，还很浪费
 |
| SetRemoteIPHost | 链接到的远程IPHost，支持域名。支持类型：
1. 使用IP&Port，传入形如：127.0.0.1:7789的字符串即可。
2. 使用域名，必须包含协议类型，形如：http://baidu.com或者https://baidu.com:80
 |
| SetReceiveType | 接收类型。
- AUTO：自动接收模式。
- None：不投递IO接收申请，用户可通过GetStream，获取到流以后，自己处理接收。注意：连接端不会感知主动断开。
 |
| UsePlugin | 是否启用插件。在启用时或许会带来一点点性能损耗，基本上不是千万数据交互根本不值一提。 |
| SetClientSslOption | Ssl配置，为Null时则不启用。
注意，当RemoteIPHost使用https、wss的域名时，该配置会使用系统默认配置生效。 |
| SetKeepAliveValue | 为Socket设置的属性。
注意：该配置仅在window平台生效。 |
| SetBindIPHost | 绑定端口。
- 在UdpSessionBase中表示本地监听地址
- 在TcpClient中表示固定客户端端口号。
 |
| SetMaxPackageSize | 数据包最大值，默认1024*1024*10。该值会在适当时间，直接作用于DataHandlingAdapter.MaxPackageSize属性。 |
| UseNoDelay | 设置Socket的NoDelay属性，默认false。 |
| UseDelaySender | 使用延迟[延迟缓存发送](https://www.yuque.com/rrqm/touchsocket/1f21a56ee75f896a5b5b38b37b071881#RL0kx)。 |
| UseReuseAddress | 启用端口复用。该配置可在服务器、或客户端在监听端口时，运行监听同一个端口。可以一定程度缓解端口来不及释放的问题 |

## 六、支持插件接口客户端、服务器均支持
声明自定义实例类，然后实现**ITcpPlugin**接口，即可实现下列事务的触发。
或者继承自**TcpPluginBase**类，重写相应方法即可。

| ###  ITcpPlugin
 |  |
| --- | --- |
| OnConnected | 客户端连接成功后触发 |
| OnConnecting | 在即将完成连接时触发。 |
| OnDisconnected | 会话断开后触发 |
| OnReceivedData | 在收到数据时触发 |
| OnSendingData | 当即将发送数据时，调用该方法在适配器之后，接下来即会发送数据。 |
| OnIDChanged | 当Client的ID被更改后触发 |

## 七、创建TcpClient
简单的处理逻辑可通过**Connecting**、**Connected**、**Received**等委托直接实现。

代码如下：
```csharp
TcpClient tcpClient = new TcpClient();
tcpClient.Connected += (client, e) => { };//成功连接到服务器
tcpClient.Disconnected += (client, e) => { };//从服务器断开连接，当连接不成功时不会触发。
tcpClient.Received += (client, byteBlock, requestInfo) =>
{
    //从服务器收到信息
    string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
    Console.WriteLine($"接收到信息：{mes}");
};

//声明配置
TouchSocketConfig config = new TouchSocketConfig();
config.SetRemoteIPHost(new IPHost("127.0.0.1:7789"))
    .UsePlugin();

//载入配置
tcpClient.Setup(config);
tcpClient.Connect();
tcpClient.Send("RRQM");
```

## 八、接收数据
在TcpClient中，接收数据的方式有很多种。多种方式可以组合使用。

#### 8.1 Received委托处理
当使用TcpClient创建客户端时，内部已经定义好了一个外置委托Received，可以通过该委托直接接收数据。
```csharp
TcpClient tcpClient = new TcpClient();
tcpClient.Received += (client, byteBlock, requestInfo) =>
{
    //从服务器收到信息
    string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
    Console.WriteLine($"接收到信息：{mes}");
};

//声明配置
TouchSocketConfig config = new TouchSocketConfig();
config.SetRemoteIPHost(new IPHost("127.0.0.1:7789"))
    .UsePlugin();

//载入配置
tcpClient.Setup(config);
tcpClient.Connect();
```

#### 8.2 插件处理推荐
按照TouchSocket的设计理念，使用插件处理数据，是一项非常简单，且高度解耦的方式。步骤如下：

1. 服务器配置启用插件（UsePlugin）
2. 新建插件类
3. 添加插件

代码如下：
（1）声明插件
```csharp
public class MyPlugin : TcpPluginBase<TcpClient>
{
    public MyPlugin()
    {
        this.Order = 0;//此值表示插件的执行顺序，当多个插件并存时，该值越大，越在前执行。
    }
   
    protected override void OnReceivedData(TcpClient client, ReceivedDataEventArgs e)
    {
        //这里处理数据接收
        //根据适配器类型，e.ByteBlock与e.RequestInfo会呈现不同的值，具体看文档=》适配器部分。
        ByteBlock byteBlock = e.ByteBlock;
        IRequestInfo requestInfo = e.RequestInfo;

        //e.Handled = true;//表示该数据已经被本插件处理，无需再投递到其他插件。
        base.OnReceivedData(client, e);
    }
}
```
（2）创建使用插件处理的客户端
```csharp
TcpClient client = new TcpClient();
client.Setup(new TouchSocketConfig()
    .SetRemoteIPHost(new IPHost("127.0.0.1:7789"))
    .UsePlugin()
    .ConfigureContainer(a=>
    {
        a.AddConsoleLogger();
    })
    .ConfigurePlugins(a => 
    {
        a.Add<MyPlugin>();
    }))
    .Connect();
```

## 九、发送数据
【同步发送】
TcpClient已经内置了三种同步发送方法，直接调用就可以发送，但需要注意的是，通过该方法发送的数据，会经过**适配器**，如果想要直接发送，请使用**DefaultSend**。如果发送失败，则会立即抛出异常。
```csharp
public virtual void Send(byte[] buffer);
public virtual void Send(ByteBlock byteBlock);
public virtual void Send(byte[] buffer, int offset, int length);
```

【异步发送】
TcpClient已经内置了三种异步发送方法，直接调用就可以发送。如果发送失败，await就会触发异常。
```csharp
public virtual Task SendAsync(byte[] buffer);
public virtual Task SendAsync(byte[] buffer, int offset, int length);
```

